package com.stars.easyms.datasource.interceptor;

import com.stars.easyms.datasource.exception.DataSourceInterceptorException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;

/**
 * <p>className: AbstractMethodInterceptor</p>
 * <p>description: 方法拦截器抽象类</p>
 *
 * @author guoguifang
 * @version 1.2.1
 * @date 2019-05-10 15:46
 */
abstract class AbstractMethodInterceptor implements MethodInterceptor {

    private static String[] ignoreMethodNames = new String[]{"toString", "getClass", "equals", "hashCode", "wait", "notify", "notifyAll", "clone"};

    private boolean ignoreObjectMethod;

    AbstractMethodInterceptor() {
        this.ignoreObjectMethod = true;
    }

    AbstractMethodInterceptor(boolean ignoreObjectMethod) {
        this.ignoreObjectMethod = ignoreObjectMethod;
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws DataSourceInterceptorException {
        // 获取当前方法，如果是底层Object对象的方法则跳过拦截
        if (ignoreObjectMethod) {
            Method method = methodInvocation.getMethod();
            for (String ignoreMethodName : ignoreMethodNames) {
                if (ignoreMethodName.equals(method.getName())) {
                    return proceed(methodInvocation);
                }
            }
        }
        return intercept(methodInvocation);
    }

    Object proceed(MethodInvocation methodInvocation) throws DataSourceInterceptorException {
        try {
            return methodInvocation.proceed();
        } catch (DataSourceInterceptorException e) {
            throw e;
        } catch (Throwable t) {
            Method method = methodInvocation.getMethod();
            throw new DataSourceInterceptorException("Invocation '{}' method '{}' execute failure!", method.getDeclaringClass().getName(), method.getName(), t);
        }
    }

    /**
     * 拦截器拦截方法后的具体实现方法
     *
     * @param methodInvocation 拦截器封装拦截方法的对象
     * @return
     * @throws DataSourceInterceptorException
     */
    abstract Object intercept(MethodInvocation methodInvocation) throws DataSourceInterceptorException;
}